package jcolorlinez;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Grid {
	private int[][] model;
	private int maxValue;
	private String saveFile;
	private Random rand = new Random();
	private int selectedRow;
	private int selectedCol;
	public Grid(int rows, int cols, int maxValue, String saveFile) {
		this.model = new int[rows][cols];
		this.maxValue= maxValue;
		this.saveFile = saveFile;
		this.selectedRow = rand.nextInt(getRows());
		this.selectedCol = rand.nextInt(getColumns());
	}
	public int getRows() {
		return model.length;
	}
	public int getColumns() {
		return model[0].length;
	}
	public int get(int row, int col) {
		return model[row][col];
	}
	public void set(int row, int col, int value) {
		model[row][col] = value;
		alert(row, col);
	}
	public int getSelectedRow() {
		return selectedRow;
	}
	public int getSelectedCol() {
		return selectedCol;
	}
	public void init() {
		for (int row = 0; row < getRows(); row++) {
			for (int col = 0; col < getColumns(); col++) {
				set(row, col, rand.nextInt(maxValue + 1));
			}
		}
	}
	public boolean save() {
		try (PrintWriter out = new PrintWriter(new FileWriter(saveFile));) {
			for (int row = 0; row < getRows(); row++) {
				for (int col = 0; col < getColumns(); col++) {
					out.print(get(row, col) + " ");
				}
				out.println();
			}
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}
	public boolean load() {
		File file = new File(saveFile);
		if (! file.exists()) {
			return false;
		}
		try (FileReader in = new FileReader(file);) {
			char[] cbuf = new char[(int)file.length()];
			in.read(cbuf);
			String[] values = new String(cbuf).split("[ \r\n\t]+");
			if (values.length != getRows()*getColumns()) {
				return false;
			}
			int index = 0;
			for (int row=0; row<getRows(); row++) {
				for (int col=0; col<getColumns(); col++) {
					set(row, col, Integer.parseInt(values[index++]));
				}
			}
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}
	public static interface Observer {
		void update(int row, int col);
	}
	private List<Observer> observers = new ArrayList<>();
	public void addObserver(Observer ob) {
		observers.add(ob);
	}
	private void alert(int row, int col) { 
		for (Observer ob : observers) {
			ob.update(row, col);
		}
	}
	
	private void unselect() {
		int unselectedRow = selectedRow;
		int unselectedCol = selectedCol;
		selectedRow = -1;
		selectedCol = -1;
		alert(unselectedRow, unselectedCol);
	}
	public void click(int row, int col) {
		if (get(row, col) > 0) { //[select]click on a chess
			if (selectedRow != -1) { //undo select old if necessary
				unselect();
			}
			selectedRow = row; //select new
			selectedCol = col;
			alert(row, col);
		} else if (selectedRow != -1) { //[move]click on an empty place when a chess is selected
			step(selectedRow, selectedCol, row, col);
			unselect();
		}
	}
	private void step(int fromRow, int fromCol, int toRow, int toCol) {
		set(toRow, toCol, get(fromRow, fromCol));
		set(fromRow, fromCol, 0);
	}
}
